package com.main.shake;




import com.main.common.Response;
import com.main.exception.TooFrequentRequestException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

@Aspect
@Component
public class AntiShakeAspect {
    @Resource
    private RedisTemplate redisTemplate;
    // 使用 AtomicLong 来确保线程安全
    private AtomicLong lastInvokeTime = new AtomicLong(0L);
    private final RedissonClient redissonClient; // Redisson客户端
    private static final String LOCK_NAME = "antiShakeLock"; // 锁名称
    private static final String LAST_INVOKE_TIME_KEY = "lastInvokeTime"; // 存储最后调用时间的键

    // 构造函数注入RedissonClient
    public AntiShakeAspect(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Around("@annotation(antiShake)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint, AntiShake antiShake) throws Throwable {
        // 获取当前时间
//        long currentTime = System.currentTimeMillis();
        //单机模式
//        synchronized (this) { // 添加同步块
//            // 获取最后一次调用的时间
//            long previousTime = lastInvokeTime.get();
//
//            if (currentTime - previousTime <= antiShake.value()) {
//                throw new TooFrequentRequestException("请求过于频繁，请稍后再试!");
//            }
//
//            try {
//                Object result = joinPoint.proceed();
//                lastInvokeTime.set(currentTime);
//                return result;
//            } catch (TooFrequentRequestException e) {
//                // 如果捕获到 TooFrequentRequestException，则直接重新抛出
//                throw e;
//            } catch (Exception e) {
//                // 其他异常情况的处理
//                throw e;
//            }
//        }
//        分布式
        RLock lock = redissonClient.getLock(LOCK_NAME); // 获取锁对象
        try {
            // 尝试获取锁，设置超时时间和等待时间
            boolean isLocked = lock.tryLock(0, -1, TimeUnit.SECONDS);
            if (!isLocked) {
                throw new TooFrequentRequestException("请求过于频繁，请稍后再试!");
            }

            long currentTime = System.currentTimeMillis();
            // 获取最后一次调用的时间
            Long previousTime = (Long) redissonClient.getMapCache(LAST_INVOKE_TIME_KEY).get("time");
            if (previousTime == null) {
                previousTime = 0L;
            }

            if (currentTime - previousTime <= antiShake.value()) {
                throw new TooFrequentRequestException("请求过于频繁，请稍后再试!");
            }

            Object result = joinPoint.proceed(); // 执行业务逻辑
            // 更新最后一次调用时间
            redissonClient.getMapCache(LAST_INVOKE_TIME_KEY).put("time", currentTime);
            return result;
        } finally {
            if (lock.isHeldByCurrentThread()) { // 确保当前线程持有锁
                lock.unlock(); // 释放锁
            }
        }
    }
}
